home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Misc / emu / fbzx.lha / fbzx / menus.c < prev    next >
C/C++ Source or Header  |  2004-01-06  |  42KB  |  2,003 lines

  1. #include "Z80.h"
  2. #include "computer.h"
  3. #include "emulator.h"
  4. #include "cargador.h"
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <dirent.h>
  11. #include <string.h>
  12. #include "characters.h"
  13. #include "menus.h"
  14. #include "tape.h"
  15. #include <SDL/SDL.h>
  16.  
  17.  
  18. // shows the settings menu
  19.  
  20. void settings_menu() {
  21.  
  22.   unsigned char *fbuffer,fin;
  23.   unsigned char texto[41];
  24.   int ancho=screen->w;
  25.  
  26.   fbuffer=screen->pixels;
  27.  
  28.   fin=1;
  29.  
  30.   texto[0]=0;
  31.  
  32.   do {
  33.     clean_screen();
  34.  
  35.     printstring(fbuffer,"Current settings",-1,5,31,16,ancho);
  36.     switch(ordenador.mode128k) {
  37.     case 0:
  38.       if(ordenador.issue==2)
  39.     sprintf(texto,"Mode: 48K issue2");
  40.       else
  41.     sprintf(texto,"Mode: 48K issue3");
  42.       break;
  43.     case 1:
  44.       sprintf(texto,"Mode: Sinclair 128K");
  45.       break;
  46.     case 2:
  47.       sprintf(texto,"Mode: Amstrad +2");
  48.       break;
  49.     case 3:
  50.       sprintf(texto,"Mode: Amstrad +2A/+3");
  51.       break;
  52.     }
  53.   
  54.     printstring(fbuffer,texto,-1,55,30,16,ancho);
  55.  
  56.     switch(ordenador.joystick) {
  57.     case 0:
  58.       sprintf(texto,"Joystick emulation: Cursor");
  59.       break;
  60.     case 1:
  61.       sprintf(texto,"Joystick emulation: Kempston");
  62.       break;
  63.     case 2:
  64.       sprintf(texto,"Joystick emulation: Sinclair (1)");
  65.       break;
  66.     case 3:
  67.       sprintf(texto,"Joystick emulation: Sinclair (2)");
  68.       break;
  69.     }
  70.     printstring(fbuffer,texto,-1,75,29,16,ancho);      
  71.  
  72.     if(ordenador.ay_emul)
  73.       sprintf(texto,"AY-3-8912 Emulation: enabled");
  74.     else
  75.       sprintf(texto,"AY-3-8912 Emulation: disabled");
  76.  
  77.     printstring(fbuffer,texto,-1,95,27,16,ancho);
  78.  
  79.     if(ordenador.mdr_active)
  80.         sprintf(texto,"Interface I Emulation: enabled");
  81.     else
  82.         sprintf(texto,"Interface I Emulation: disabled");
  83.     
  84.     printstring(fbuffer,texto,-1,115,28,16,ancho);
  85.     
  86.     printstring(fbuffer,"F1:",30,160,28,16,ancho);
  87.     printstring(fbuffer,"48K issue2",78,160,31,16,ancho);
  88.  
  89.     printstring(fbuffer,"F2:",350,160,28,16,ancho);
  90.     printstring(fbuffer,"48K issue3",398,160,31,16,ancho);
  91.  
  92.     printstring(fbuffer,"F3:",30,200,28,16,ancho);
  93.     printstring(fbuffer,"Sinclair 128K",78,200,31,16,ancho);
  94.  
  95.     printstring(fbuffer,"F4:",350,200,28,16,ancho);
  96.     printstring(fbuffer,"Amstrad +2",398,200,31,16,ancho);
  97.  
  98.     printstring(fbuffer,"F5:",30,240,28,16,ancho);
  99.     printstring(fbuffer,"Amstrad +2A/+3",78,240,31,16,ancho);
  100.  
  101.     printstring(fbuffer,"F6:",350,240,28,16,ancho);
  102.     printstring(fbuffer,"AY emulation",398,240,31,16,ancho);
  103.  
  104.     printstring(fbuffer,"F7:",30,280,28,16,ancho);
  105.     printstring(fbuffer,"Cursor",78,280,31,16,ancho);
  106.  
  107.     printstring(fbuffer,"F8:",350,280,28,16,ancho);
  108.     printstring(fbuffer,"Kempston",398,280,31,16,ancho);
  109.  
  110.     printstring(fbuffer,"F9:",30,320,28,16,ancho);
  111.     printstring(fbuffer,"Sinclair (1)",78,320,31,16,ancho);
  112.  
  113.     printstring(fbuffer,"F10:",350,320,28,16,ancho);
  114.     printstring(fbuffer,"Sinclair (2)",414,320,31,16,ancho);
  115.  
  116.     printstring(fbuffer,"F11:",30,360,28,16,ancho);
  117.     printstring(fbuffer,"Interface I",94,360,31,16,ancho);
  118.  
  119.     printstring(fbuffer,"ESC:",168,400,28,16,ancho);
  120.     printstring(fbuffer,"return emulator",232,400,31,16,ancho);
  121.  
  122.     switch(wait_key()) {
  123.     case SDLK_ESCAPE:
  124.     case SDLK_RETURN:
  125.       fin=0;
  126.       break;
  127.  
  128.     case SDLK_F1:
  129.       ordenador.issue=2;
  130.       ordenador.mode128k=0;
  131.       ordenador.ay_emul=0;
  132.       ResetComputer();
  133.       break;
  134.     case SDLK_F2:
  135.       ordenador.issue=3;
  136.       ordenador.mode128k=0;
  137.       ordenador.ay_emul=0;
  138.       ResetComputer();
  139.       break;
  140.     case SDLK_F3:
  141.       ordenador.issue=3;
  142.       ordenador.mode128k=1;
  143.       ordenador.ay_emul=1;
  144.       ResetComputer();
  145.       break;
  146.     case SDLK_F4:
  147.       ordenador.issue=3;
  148.       ordenador.mode128k=2;
  149.       ordenador.ay_emul=1;
  150.       ResetComputer();
  151.       break;
  152.     case SDLK_F5:
  153.       ordenador.issue=3;
  154.       ordenador.mode128k=3;
  155.       ordenador.ay_emul=1;
  156.       ordenador.mdr_active=0;
  157.       ResetComputer();
  158.       break;
  159.     case SDLK_F6:
  160.       ordenador.ay_emul=1-ordenador.ay_emul;
  161.       break;
  162.     case SDLK_F7:
  163.       ordenador.joystick=0;
  164.       break;
  165.     case SDLK_F8:
  166.       ordenador.joystick=1;
  167.       break;
  168.     case SDLK_F9:
  169.       ordenador.joystick=2;
  170.       break;
  171.     case SDLK_F10:
  172.       ordenador.joystick=3;
  173.       break;
  174.     case SDLK_F11:
  175.         if(ordenador.mode128k!=3) {
  176.             ordenador.mdr_active=1-ordenador.mdr_active;
  177.             ResetComputer();
  178.         }
  179.         break;
  180.     }
  181.   } while(fin);
  182.  
  183.   clean_screen();
  184.  
  185. }
  186.  
  187.  
  188. // shows the help menu
  189.  
  190. void help_menu() {
  191.  
  192.   unsigned char *fbuffer,fin;
  193.   int ancho=screen->w;
  194.  
  195.   fbuffer=screen->pixels;
  196.  
  197.   clean_screen();
  198.  
  199.   printstring(fbuffer,"FBZX (1.3)",-1,10,31,16,ancho);
  200.   printstring(fbuffer,"Available keys",-1,40,30,16,ancho);
  201.   printstring(fbuffer,"Shift:Caps Shift    Ctrl:Symbol Shift",-1,95,27,16,ancho);
  202.  
  203.   printstring(fbuffer,"F1:",14,160,28,16,ancho);
  204.   printstring(fbuffer,"this help",62,160,31,16,ancho);
  205.  
  206.   printstring(fbuffer,"F2:",336,160,28,16,ancho);
  207.   printstring(fbuffer,"manage snapshots",382,160,31,16,ancho);
  208.  
  209.   printstring(fbuffer,"F3:",14,200,28,16,ancho);
  210.   printstring(fbuffer,"manage TAP/TZX",62,200,31,16,ancho);
  211.  
  212.   printstring(fbuffer,"F4:",336,200,28,16,ancho);
  213.   printstring(fbuffer,"change settings",382,200,31,16,ancho);
  214.  
  215.   printstring(fbuffer,"F5:",14,240,28,16,ancho);
  216.   printstring(fbuffer,"stop TAPE",62,240,31,16,ancho);
  217.  
  218.   printstring(fbuffer,"F6:",336,240,28,16,ancho);
  219.   printstring(fbuffer,"play TAPE",382,240,31,16,ancho);
  220.  
  221.   printstring(fbuffer,"F7:",14,280,28,16,ancho);
  222.   printstring(fbuffer,"manage MICRODRIVE",62,280,31,16,ancho);
  223.  
  224.   printstring(fbuffer,"F10:",336,320,28,16,ancho);
  225.   printstring(fbuffer,"reset spectrum",398,320,31,16,ancho);
  226.  
  227.   printstring(fbuffer,"F11:",14,360,28,16,ancho);
  228.   printstring(fbuffer,"volume low",78,360,31,16,ancho);
  229.  
  230.   printstring(fbuffer,"F12:",336,360,28,16,ancho);
  231.   printstring(fbuffer,"F12:volume up",398,360,31,16,ancho);
  232.  
  233.   printstring(fbuffer,"ESC:",184,400,28,16,ancho);
  234.   printstring(fbuffer,"exit emulator",248,400,31,16,ancho);
  235.  
  236.   printstring(fbuffer,"(C) 2003 Raster Software Vigo",-1,455,29,16,ancho);
  237.  
  238.   fin=1;
  239.   do {
  240.  
  241.     switch(wait_key()) {
  242.     case SDLK_ESCAPE: // to exit the help
  243.       fin=0;
  244.       break;
  245.  
  246.     default:
  247.       break;
  248.     }      
  249.  
  250.   } while(fin);
  251.  
  252.   clean_screen();
  253.  
  254. }
  255.  
  256.  
  257. // shows the SNAPSHOTS menu
  258.  
  259. void snapshots_menu() {
  260.  
  261.     unsigned char *fbuffer,fin;
  262.     int ancho=screen->w;
  263.  
  264.     fbuffer=screen->pixels;
  265.  
  266.     clean_screen();
  267.  
  268.     printstring(fbuffer,"SNAPSHOTS",-1,10,31,16,ancho);
  269.  
  270.     printstring(fbuffer,"F1:",14,100,28,16,ancho);
  271.     printstring(fbuffer,"load a Z80 snapshot",62,100,31,16,ancho);
  272.  
  273.  
  274.     if(ordenador.mode128k!=3) { // not in +3 mode
  275.         printstring(fbuffer,"F2:",14,160,28,16,ancho);
  276.         printstring(fbuffer,"make a Z80 snapshot",62,160,31,16,ancho);
  277.     } else {
  278.         printstring(fbuffer,"Can't make snapshots in +3 mode",14,160,31,16,ancho);
  279.     }
  280.  
  281.     printstring(fbuffer,"ESC:",170,400,28,16,ancho);
  282.     printstring(fbuffer,"return emulator",234,400,31,16,ancho);
  283.  
  284.     printstring(fbuffer,"(C) 2003 Raster Software Vigo",-1,455,29,16,ancho);
  285.  
  286.     fin=1;
  287.     do {
  288.         switch(wait_key()) {
  289.         case SDLK_ESCAPE: // to exit the help
  290.             fin=0;
  291.         break;
  292.         case SDLK_F1:
  293.             fin=0;
  294.             load_z80file();
  295.         break;
  296.         case SDLK_F2:
  297.             fin=0;
  298.             if(ordenador.mode128k!=3) // not in +3 mode
  299.                 save_z80file();
  300.         break;
  301.         default:
  302.         break;
  303.         }      
  304.     } while(fin);
  305.  
  306.     clean_screen();
  307. }
  308.  
  309.  
  310. // shows the TAPs menu
  311.  
  312. void taps_menu() {
  313.  
  314.     unsigned char *fbuffer,fin;
  315.     int ancho=screen->w;
  316.  
  317.     fbuffer=screen->pixels;
  318.     
  319.     fin=1;
  320.     do {
  321.           clean_screen();
  322.  
  323.         printstring(fbuffer,"TAP/TZX files",-1,10,31,16,ancho);
  324.  
  325.         printstring(fbuffer,"F1:",14,50,28,16,ancho);
  326.         printstring(fbuffer,"select a TAP/TZX file",62,50,31,16,ancho);
  327.  
  328.  
  329.         printstring(fbuffer,"F2:",14,90,28,16,ancho);
  330.         printstring(fbuffer,"rewind TAP/TZX file",62,90,31,16,ancho);
  331.  
  332.         printstring(fbuffer,"F3:",14,130,28,16,ancho);
  333.         printstring(fbuffer,"fast/normal speed",62,130,31,16,ancho);
  334.  
  335.         printstring(fbuffer,"F4:",14,170,28,16,ancho);
  336.         printstring(fbuffer,"write protection",62,170,31,16,ancho);
  337.         
  338.         printstring(fbuffer,"F5:",14,210,28,16,ancho);
  339.         printstring(fbuffer,"create TAP file",62,210,31,16,ancho);
  340.                 
  341.         printstring(fbuffer,"ESC:",14,250,28,16,ancho);
  342.         printstring(fbuffer,"return emulator",78,250,31,16,ancho);
  343.  
  344.         printstring(fbuffer,"Current TAP/TZX file is:",-1,300,28,16,ancho);
  345.         printstring(fbuffer,ordenador.current_tap,-1,320,28,16,ancho);
  346.  
  347.         printstring(fbuffer,"(C) 2003 Raster Software Vigo",-1,455,29,16,ancho);
  348.  
  349.         if(ordenador.tape_fast_load)
  350.             printstring(fbuffer,"Fast load enabled  ",10,420,30,16,ancho);
  351.         else
  352.             printstring(fbuffer,"Fast load disabled ",10,420,30,16,ancho);
  353.         
  354.         if(ordenador.tape_write)
  355.             printstring(fbuffer,"Write enabled  ",390,420,30,16,ancho);
  356.         else
  357.             printstring(fbuffer,"Write disabled ",390,420,30,16,ancho);
  358.     
  359.         switch(wait_key()) {
  360.         case SDLK_ESCAPE: // to exit the help
  361.             fin=0;
  362.         break;
  363.  
  364.         case SDLK_F1:
  365.             ordenador.pause=1;
  366.             select_tapfile();
  367.         break;
  368.         case SDLK_F2:
  369.             fin=0;
  370.             ordenador.pause=1;
  371.             if(ordenador.tap_file!=NULL) {
  372.                 ordenador.tape_current_mode=TAP_TRASH;
  373.                 rewind_tape(ordenador.tap_file,1);        
  374.             }
  375.             sprintf(ordenador.osd_text,"Tape rewinded");
  376.             ordenador.osd_time=50;            
  377.         break;
  378.         case SDLK_F3:
  379.             ordenador.pause=1;
  380.             ordenador.tape_fast_load=1-ordenador.tape_fast_load;
  381.             if(ordenador.tap_file!=NULL) {
  382.                 ordenador.tape_current_mode=TAP_TRASH;
  383.                 rewind_tape(ordenador.tap_file,1);
  384.             }
  385.         break;
  386.         case SDLK_F4:
  387.             ordenador.tape_write=1-ordenador.tape_write;
  388.         break;
  389.         case SDLK_F5:
  390.             create_tapfile();
  391.         break;
  392.         default:
  393.         break;
  394.         }      
  395.  
  396.     } while(fin);
  397.  
  398.     clean_screen();
  399. }
  400.  
  401. // shows a menu to allow user to choose a tape file
  402.  
  403. void select_tapfile() {
  404.  
  405.     unsigned char *videomem,*filename;
  406.     int ancho,retorno;
  407.     unsigned char char_id[11];
  408.  
  409.   videomem=screen->pixels;
  410.   ancho=screen->w;
  411.  
  412.   clean_screen();
  413.  
  414.   if(ordenador.tap_file!=NULL)
  415.     rewind_tape(ordenador.tap_file,1);
  416.   ordenador.tape_current_bit=0;
  417.   ordenador.tape_current_mode=TAP_TRASH;
  418.  
  419.   printstring(videomem,"Choose the TAPE file to load",-1,32,29,16,ancho);
  420.  
  421.   filename=select_file(path_taps,1);
  422.  
  423.   if(filename==NULL) { // Aborted
  424.     clean_screen();
  425.     return;
  426.   }
  427.  
  428.   if(ordenador.tap_file!=NULL)
  429.     fclose(ordenador.tap_file);
  430.   ordenador.tap_file=fopen(filename,"r+"); // read and write
  431.   ordenador.tape_write = 0; // by default, can't record
  432.   if(ordenador.tap_file==NULL)
  433.     retorno=-1;
  434.   else
  435.     retorno=0;
  436.  
  437.   clean_screen();
  438.  
  439.   strcpy(ordenador.current_tap,filename);
  440.  
  441.   free(filename);
  442.   
  443.   switch(retorno) {
  444.   case 0: // all right
  445.     break;
  446.   case -1:
  447.     printstring(videomem,"Error: Can't load that file",-1,232,26,16,ancho);
  448.     printstring(videomem,"Press any key",-1,248,26,16,ancho);
  449.     ordenador.current_tap[0]=0;
  450.     wait_key();
  451.     break;
  452.   }
  453.   
  454.   fread(char_id,10,1,ordenador.tap_file); // read the (maybe) TZX header
  455.   if((!strncmp(char_id,"ZXTape!",7)) && (char_id[7]==0x1A)&&(char_id[8]==1)) {
  456.       ordenador.tape_file_type = TAP_TZX;
  457.       rewind_tape(ordenador.tap_file,1);      
  458.   } else {
  459.       ordenador.tape_file_type = TAP_TAP;
  460.       rewind_tape(ordenador.tap_file,1);
  461.   }
  462.   
  463.   clean_screen();
  464. }
  465.  
  466. void create_tapfile() {
  467.  
  468.     unsigned char *videomem;
  469.     int ancho,retorno,longitud;
  470.     unsigned char nombre[35],nombre2[37];
  471.  
  472.     videomem=screen->pixels;
  473.     ancho=screen->w;
  474.  
  475.     clean_screen();
  476.  
  477.     printstring(videomem,"Choose a name for the TAP file",-1,32,30,16,ancho);
  478.     printstring(videomem,"(up to 30 characters)",-1,52,30,16,ancho);
  479.  
  480.     printstring(videomem,"TAP file will be saved in:",-1,132,28,16,ancho);
  481.     printstring(videomem,path_taps,0,152,28,16,ancho);
  482.  
  483.     nombre[0]=127;
  484.     nombre[1]=0;
  485.     longitud=0;
  486.     retorno=0;
  487.  
  488.     do {
  489.         sprintf(nombre2," %s ",nombre);
  490.         printstring(videomem,nombre2,-1,84,31,16,ancho);
  491.         switch(wait_key()) {
  492.         case SDLK_BACKSPACE:
  493.             if(longitud>0) {
  494.                 nombre[longitud]=0;
  495.                 longitud--;
  496.                 nombre[longitud]=127;
  497.             }
  498.         break;
  499.         case SDLK_ESCAPE:
  500.             retorno=2;
  501.         break;
  502.         case SDLK_RETURN:
  503.             retorno=1;
  504.         break;
  505.         case SDLK_a:
  506.             if(longitud<30) {
  507.                 nombre[longitud++]='a';
  508.                 nombre[longitud]=127;
  509.                 nombre[longitud+1]=0;
  510.             }
  511.         break;
  512.         case SDLK_b:
  513.             if(longitud<30) {
  514.                 nombre[longitud++]='b';
  515.                 nombre[longitud]=127;
  516.                 nombre[longitud+1]=0;
  517.             }
  518.         break;
  519.     case SDLK_c:
  520.       if(longitud<30) {
  521.     nombre[longitud++]='c';
  522.     nombre[longitud]=127;
  523.     nombre[longitud+1]=0;
  524.       }
  525.       break;
  526.     case SDLK_d:
  527.       if(longitud<30) {
  528.     nombre[longitud++]='d';
  529.     nombre[longitud]=127;
  530.     nombre[longitud+1]=0;
  531.       }
  532.       break;
  533.     case SDLK_e:
  534.       if(longitud<30) {
  535.     nombre[longitud++]='e';
  536.     nombre[longitud]=127;
  537.     nombre[longitud+1]=0;
  538.       }
  539.       break;
  540.     case SDLK_f:
  541.       if(longitud<30) {
  542.     nombre[longitud++]='f';
  543.     nombre[longitud]=127;
  544.     nombre[longitud+1]=0;
  545.       }
  546.       break;
  547.     case SDLK_g:
  548.       if(longitud<30) {
  549.     nombre[longitud++]='g';
  550.     nombre[longitud]=127;
  551.     nombre[longitud+1]=0;
  552.       }
  553.       break;
  554.     case SDLK_h:
  555.       if(longitud<30) {
  556.     nombre[longitud++]='h';
  557.     nombre[longitud]=127;
  558.     nombre[longitud+1]=0;
  559.       }
  560.       break;
  561.     case SDLK_i:
  562.       if(longitud<30) {
  563.     nombre[longitud++]='i';
  564.     nombre[longitud]=127;
  565.     nombre[longitud+1]=0;
  566.       }
  567.       break;
  568.     case SDLK_j:
  569.       if(longitud<30) {
  570.     nombre[longitud++]='j';
  571.     nombre[longitud]=127;
  572.     nombre[longitud+1]=0;
  573.       }
  574.       break;
  575.     case SDLK_k:
  576.       if(longitud<30) {
  577.     nombre[longitud++]='k';
  578.     nombre[longitud]=127;
  579.     nombre[longitud+1]=0;
  580.       }
  581.       break;
  582.     case SDLK_l:
  583.       if(longitud<30) {
  584.     nombre[longitud++]='l';
  585.     nombre[longitud]=127;
  586.     nombre[longitud+1]=0;
  587.       }
  588.       break;
  589.     case SDLK_m:
  590.       if(longitud<30) {
  591.     nombre[longitud++]='m';
  592.     nombre[longitud]=127;
  593.     nombre[longitud+1]=0;
  594.       }
  595.       break;
  596.     case SDLK_n:
  597.       if(longitud<30) {
  598.     nombre[longitud++]='n';
  599.     nombre[longitud]=127;
  600.     nombre[longitud+1]=0;
  601.       }
  602.       break;
  603.     case SDLK_o:
  604.       if(longitud<30) {
  605.     nombre[longitud++]='o';
  606.     nombre[longitud]=127;
  607.     nombre[longitud+1]=0;
  608.       }
  609.       break;
  610.     case SDLK_p:
  611.       if(longitud<30) {
  612.     nombre[longitud++]='p';
  613.     nombre[longitud]=127;
  614.     nombre[longitud+1]=0;
  615.       }
  616.       break;
  617.     case SDLK_q:
  618.       if(longitud<30) {
  619.     nombre[longitud++]='q';
  620.     nombre[longitud]=127;
  621.     nombre[longitud+1]=0;
  622.       }
  623.       break;
  624.     case SDLK_r:
  625.       if(longitud<30) {
  626.     nombre[longitud++]='r';
  627.     nombre[longitud]=127;
  628.     nombre[longitud+1]=0;
  629.       }
  630.       break;
  631.     case SDLK_s:
  632.       if(longitud<30) {
  633.     nombre[longitud++]='s';
  634.     nombre[longitud]=127;
  635.     nombre[longitud+1]=0;
  636.       }
  637.       break;
  638.     case SDLK_t:
  639.       if(longitud<30) {
  640.     nombre[longitud++]='t';
  641.     nombre[longitud]=127;
  642.     nombre[longitud+1]=0;
  643.       }
  644.       break;
  645.     case SDLK_u:
  646.       if(longitud<30) {
  647.     nombre[longitud++]='u';
  648.     nombre[longitud]=127;
  649.     nombre[longitud+1]=0;
  650.       }
  651.       break;
  652.     case SDLK_v:
  653.       if(longitud<30) {
  654.     nombre[longitud++]='v';
  655.     nombre[longitud]=127;
  656.     nombre[longitud+1]=0;
  657.       }
  658.       break;
  659.     case SDLK_w:
  660.       if(longitud<30) {
  661.     nombre[longitud++]='w';
  662.     nombre[longitud]=127;
  663.     nombre[longitud+1]=0;
  664.       }
  665.       break;
  666.     case SDLK_x:
  667.       if(longitud<30) {
  668.     nombre[longitud++]='x';
  669.     nombre[longitud]=127;
  670.     nombre[longitud+1]=0;
  671.       }
  672.       break;
  673.     case SDLK_y:
  674.       if(longitud<30) {
  675.     nombre[longitud++]='y';
  676.     nombre[longitud]=127;
  677.     nombre[longitud+1]=0;
  678.       }
  679.       break;
  680.     case SDLK_z:
  681.       if(longitud<30) {
  682.     nombre[longitud++]='z';
  683.     nombre[longitud]=127;
  684.     nombre[longitud+1]=0;
  685.       }
  686.       break;
  687.     case SDLK_0:
  688.       if(longitud<30) {
  689.     nombre[longitud++]='0';
  690.     nombre[longitud]=127;
  691.     nombre[longitud+1]=0;
  692.       }
  693.       break;
  694.     case SDLK_1:
  695.       if(longitud<30) {
  696.     nombre[longitud++]='1';
  697.     nombre[longitud]=127;
  698.     nombre[longitud+1]=0;
  699.       }
  700.       break;
  701.     case SDLK_2:
  702.       if(longitud<30) {
  703.     nombre[longitud++]='2';
  704.     nombre[longitud]=127;
  705.     nombre[longitud+1]=0;
  706.       }
  707.       break;
  708.     case SDLK_3:
  709.       if(longitud<30) {
  710.     nombre[longitud++]='3';
  711.     nombre[longitud]=127;
  712.     nombre[longitud+1]=0;
  713.       }
  714.       break;
  715.     case SDLK_4:
  716.       if(longitud<30) {
  717.     nombre[longitud++]='4';
  718.     nombre[longitud]=127;
  719.     nombre[longitud+1]=0;
  720.       }
  721.       break;
  722.     case SDLK_5:
  723.       if(longitud<30) {
  724.     nombre[longitud++]='5';
  725.     nombre[longitud]=127;
  726.     nombre[longitud+1]=0;
  727.       }
  728.       break;
  729.     case SDLK_6:
  730.       if(longitud<30) {
  731.     nombre[longitud++]='6';
  732.     nombre[longitud]=127;
  733.     nombre[longitud+1]=0;
  734.       }
  735.       break;
  736.     case SDLK_7:
  737.       if(longitud<30) {
  738.     nombre[longitud++]='7';
  739.     nombre[longitud]=127;
  740.     nombre[longitud+1]=0;
  741.       }
  742.       break;
  743.         case SDLK_8:
  744.             if(longitud<30) {
  745.                 nombre[longitud++]='8';
  746.                 nombre[longitud]=127;
  747.                   nombre[longitud+1]=0;
  748.             }
  749.         break;
  750.         case SDLK_9:
  751.             if(longitud<30) {
  752.                 nombre[longitud++]='9';
  753.                 nombre[longitud]=127;
  754.                   nombre[longitud+1]=0;
  755.             }
  756.         break;
  757.         case SDLK_MINUS:
  758.             if(longitud<30) {
  759.                 nombre[longitud++]='-';
  760.                   nombre[longitud]=127;
  761.                   nombre[longitud+1]=0;
  762.             }
  763.         break;
  764.         }
  765.     } while(!retorno);
  766.  
  767.     clean_screen();
  768.  
  769.     nombre[longitud]=0; // erase cursor
  770.  
  771.     if(retorno==2) // abort
  772.         return;
  773.  
  774.     longitud=strlen(path_taps);
  775.     if((path_snaps[longitud-1]!='/')&&(longitud>1))
  776.         sprintf(nombre2,"%s/%s.tap",path_taps,nombre); // name
  777.     else
  778.         sprintf(nombre2,"%s%s.tap",path_taps,nombre);
  779.     if(ordenador.tap_file!=NULL)
  780.         fclose(ordenador.tap_file);
  781.     
  782.     ordenador.tap_file=fopen(nombre2,"r"); // test if it exists
  783.     if(ordenador.tap_file==NULL)
  784.         retorno=0;
  785.     else
  786.         retorno=-1;
  787.     
  788.     if(!retorno) {
  789.         ordenador.tap_file=fopen(nombre2,"a+"); // create for read and write
  790.         if(ordenador.tap_file==NULL)
  791.             retorno=-2;
  792.         else
  793.             retorno=0;
  794.     }
  795.     ordenador.tape_write=1; // allow to write
  796.     strcpy(ordenador.current_tap,nombre2);
  797.     ordenador.tape_file_type = TAP_TAP;
  798.     switch(retorno) {
  799.     case 0:
  800.     break;
  801.     case -1:
  802.         printstring(videomem,"File already exists",-1,80,26,16,ancho);
  803.         ordenador.current_tap[0]=0;
  804.         wait_key();
  805.     break;
  806.     case -2:
  807.         printstring(videomem,"Can't create file",-1,80,26,16,ancho);
  808.         ordenador.current_tap[0]=0;
  809.         wait_key();
  810.     break;
  811.     }
  812.     clean_screen();
  813. }
  814.  
  815. // shows the microdrive menu
  816.  
  817. void microdrive_menu() {
  818.  
  819.     unsigned char *fbuffer,fin;
  820.     int ancho=screen->w;
  821.  
  822.     fbuffer=screen->pixels;
  823.     
  824.     fin=1;
  825.     do {
  826.           clean_screen();
  827.  
  828.         printstring(fbuffer,"MICRODRIVE files",-1,10,31,16,ancho);
  829.  
  830.         printstring(fbuffer,"F1:",14,50,28,16,ancho);
  831.         printstring(fbuffer,"select a MDR file",62,50,31,16,ancho);
  832.  
  833.         printstring(fbuffer,"F2:",14,90,28,16,ancho);
  834.         printstring(fbuffer,"create a MDR file",62,90,31,16,ancho);
  835.  
  836.         printstring(fbuffer,"F3:",14,130,28,16,ancho);
  837.         printstring(fbuffer,"write protection",62,130,31,16,ancho);
  838.                 
  839.         printstring(fbuffer,"ESC:",14,170,28,16,ancho);
  840.         printstring(fbuffer,"return emulator",78,170,31,16,ancho);
  841.  
  842.         printstring(fbuffer,"Current MDR file is:",-1,300,28,16,ancho);
  843.         printstring(fbuffer,ordenador.mdr_current_mdr,-1,320,28,16,ancho);
  844.  
  845.         printstring(fbuffer,"(C) 2003 Raster Software Vigo",-1,455,29,16,ancho);
  846.         
  847.         if(!ordenador.mdr_cartridge[137922])
  848.             printstring(fbuffer,"  Write enabled  ",-1,420,30,16,ancho);
  849.         else
  850.             printstring(fbuffer," Write disabled ",-1,420,30,16,ancho);
  851.     
  852.         switch(wait_key()) {
  853.         case SDLK_ESCAPE: // to exit the help
  854.             fin=0;
  855.             break;
  856.  
  857.         case SDLK_F1:            
  858.             select_mdrfile();
  859.             break;
  860.         case SDLK_F2:
  861.             create_mdrfile();
  862.             break;
  863.         case SDLK_F3:
  864.             if(ordenador.mdr_cartridge[137922])
  865.                 ordenador.mdr_cartridge[137922]=0;
  866.             else
  867.                 ordenador.mdr_cartridge[137922]=1;
  868.             ordenador.mdr_file=fopen(ordenador.mdr_current_mdr,"wb"); // create for write
  869.             if(ordenador.mdr_file!=NULL) {                
  870.                 fwrite(ordenador.mdr_cartridge,137923,1,ordenador.mdr_file); // save cartridge
  871.                 fclose(ordenador.mdr_file);
  872.                 ordenador.mdr_file=NULL;
  873.                 ordenador.mdr_modified=0;
  874.             }            
  875.             break;        
  876.         default:
  877.         break;
  878.         }      
  879.  
  880.     } while(fin);
  881.  
  882.     clean_screen();
  883. }
  884.  
  885. // shows a menu to allow user to choose a microdrive file
  886.  
  887. void select_mdrfile() {
  888.  
  889.     unsigned char *videomem,*filename;
  890.     int ancho,retorno;
  891.     // unsigned char char_id[11];
  892.  
  893.   videomem=screen->pixels;
  894.   ancho=screen->w;
  895.  
  896.   clean_screen();
  897.  
  898.   printstring(videomem,"Choose the MICRODRIVE file to load",-1,32,29,16,ancho);
  899.  
  900.   filename=select_file(path_mdrs,2); // MDR files
  901.  
  902.   if(filename==NULL) { // Aborted
  903.     clean_screen();
  904.     return;
  905.   }
  906.  
  907.   ordenador.mdr_file=fopen(filename,"rb"); // read  
  908.   if(ordenador.mdr_file==NULL)
  909.     retorno=-1;
  910.   else {
  911.     retorno=0;
  912.     fread(ordenador.mdr_cartridge,137923,1,ordenador.mdr_file); // read the cartridge in memory
  913.     ordenador.mdr_modified=0; // not modified
  914.     fclose(ordenador.mdr_file);
  915.     ordenador.mdr_tapehead=0;
  916.   }
  917.  
  918.   clean_screen();
  919.  
  920.   strcpy(ordenador.mdr_current_mdr,filename);
  921.  
  922.   free(filename);
  923.   
  924.   switch(retorno) {
  925.   case 0: // all right
  926.     break;
  927.   case -1:
  928.     printstring(videomem,"Error: Can't load that file",-1,232,26,16,ancho);
  929.     printstring(videomem,"Press any key",-1,248,26,16,ancho);
  930.     ordenador.mdr_current_mdr[0]=0;
  931.     wait_key();
  932.     break;
  933.   }
  934.  
  935.   clean_screen();
  936. }
  937.  
  938. void create_mdrfile() {
  939.  
  940.     unsigned char *videomem;
  941.     int ancho,retorno,longitud,bucle;
  942.     unsigned char nombre[35],nombre2[37];
  943.  
  944.     videomem=screen->pixels;
  945.     ancho=screen->w;
  946.  
  947.     clean_screen();
  948.  
  949.     printstring(videomem,"Choose a name for the MDR file",-1,32,30,16,ancho);
  950.     printstring(videomem,"(up to 30 characters)",-1,52,30,16,ancho);
  951.  
  952.     printstring(videomem,"MDR file will be saved in:",-1,132,28,16,ancho);
  953.     printstring(videomem,path_mdrs,0,152,28,16,ancho);
  954.  
  955.     nombre[0]=127;
  956.     nombre[1]=0;
  957.     longitud=0;
  958.     retorno=0;
  959.  
  960.     do {
  961.         sprintf(nombre2," %s ",nombre);
  962.         printstring(videomem,nombre2,-1,84,31,16,ancho);
  963.         switch(wait_key()) {
  964.         case SDLK_BACKSPACE:
  965.             if(longitud>0) {
  966.                 nombre[longitud]=0;
  967.                 longitud--;
  968.                 nombre[longitud]=127;
  969.             }
  970.         break;
  971.         case SDLK_ESCAPE:
  972.             retorno=2;
  973.         break;
  974.         case SDLK_RETURN:
  975.             retorno=1;
  976.         break;
  977.         case SDLK_a:
  978.             if(longitud<30) {
  979.                 nombre[longitud++]='a';
  980.                 nombre[longitud]=127;
  981.                 nombre[longitud+1]=0;
  982.             }
  983.         break;
  984.         case SDLK_b:
  985.             if(longitud<30) {
  986.                 nombre[longitud++]='b';
  987.                 nombre[longitud]=127;
  988.                 nombre[longitud+1]=0;
  989.             }
  990.         break;
  991.     case SDLK_c:
  992.       if(longitud<30) {
  993.     nombre[longitud++]='c';
  994.     nombre[longitud]=127;
  995.     nombre[longitud+1]=0;
  996.       }
  997.       break;
  998.     case SDLK_d:
  999.       if(longitud<30) {
  1000.     nombre[longitud++]='d';
  1001.     nombre[longitud]=127;
  1002.     nombre[longitud+1]=0;
  1003.       }
  1004.       break;
  1005.     case SDLK_e:
  1006.       if(longitud<30) {
  1007.     nombre[longitud++]='e';
  1008.     nombre[longitud]=127;
  1009.     nombre[longitud+1]=0;
  1010.       }
  1011.       break;
  1012.     case SDLK_f:
  1013.       if(longitud<30) {
  1014.     nombre[longitud++]='f';
  1015.     nombre[longitud]=127;
  1016.     nombre[longitud+1]=0;
  1017.       }
  1018.       break;
  1019.     case SDLK_g:
  1020.       if(longitud<30) {
  1021.     nombre[longitud++]='g';
  1022.     nombre[longitud]=127;
  1023.     nombre[longitud+1]=0;
  1024.       }
  1025.       break;
  1026.     case SDLK_h:
  1027.       if(longitud<30) {
  1028.     nombre[longitud++]='h';
  1029.     nombre[longitud]=127;
  1030.     nombre[longitud+1]=0;
  1031.       }
  1032.       break;
  1033.     case SDLK_i:
  1034.       if(longitud<30) {
  1035.     nombre[longitud++]='i';
  1036.     nombre[longitud]=127;
  1037.     nombre[longitud+1]=0;
  1038.       }
  1039.       break;
  1040.     case SDLK_j:
  1041.       if(longitud<30) {
  1042.     nombre[longitud++]='j';
  1043.     nombre[longitud]=127;
  1044.     nombre[longitud+1]=0;
  1045.       }
  1046.       break;
  1047.     case SDLK_k:
  1048.       if(longitud<30) {
  1049.     nombre[longitud++]='k';
  1050.     nombre[longitud]=127;
  1051.     nombre[longitud+1]=0;
  1052.       }
  1053.       break;
  1054.     case SDLK_l:
  1055.       if(longitud<30) {
  1056.     nombre[longitud++]='l';
  1057.     nombre[longitud]=127;
  1058.     nombre[longitud+1]=0;
  1059.       }
  1060.       break;
  1061.     case SDLK_m:
  1062.       if(longitud<30) {
  1063.     nombre[longitud++]='m';
  1064.     nombre[longitud]=127;
  1065.     nombre[longitud+1]=0;
  1066.       }
  1067.       break;
  1068.     case SDLK_n:
  1069.       if(longitud<30) {
  1070.     nombre[longitud++]='n';
  1071.     nombre[longitud]=127;
  1072.     nombre[longitud+1]=0;
  1073.       }
  1074.       break;
  1075.     case SDLK_o:
  1076.       if(longitud<30) {
  1077.     nombre[longitud++]='o';
  1078.     nombre[longitud]=127;
  1079.     nombre[longitud+1]=0;
  1080.       }
  1081.       break;
  1082.     case SDLK_p:
  1083.       if(longitud<30) {
  1084.     nombre[longitud++]='p';
  1085.     nombre[longitud]=127;
  1086.     nombre[longitud+1]=0;
  1087.       }
  1088.       break;
  1089.     case SDLK_q:
  1090.       if(longitud<30) {
  1091.     nombre[longitud++]='q';
  1092.     nombre[longitud]=127;
  1093.     nombre[longitud+1]=0;
  1094.       }
  1095.       break;
  1096.     case SDLK_r:
  1097.       if(longitud<30) {
  1098.     nombre[longitud++]='r';
  1099.     nombre[longitud]=127;
  1100.     nombre[longitud+1]=0;
  1101.       }
  1102.       break;
  1103.     case SDLK_s:
  1104.       if(longitud<30) {
  1105.     nombre[longitud++]='s';
  1106.     nombre[longitud]=127;
  1107.     nombre[longitud+1]=0;
  1108.       }
  1109.       break;
  1110.     case SDLK_t:
  1111.       if(longitud<30) {
  1112.     nombre[longitud++]='t';
  1113.     nombre[longitud]=127;
  1114.     nombre[longitud+1]=0;
  1115.       }
  1116.       break;
  1117.     case SDLK_u:
  1118.       if(longitud<30) {
  1119.     nombre[longitud++]='u';
  1120.     nombre[longitud]=127;
  1121.     nombre[longitud+1]=0;
  1122.       }
  1123.       break;
  1124.     case SDLK_v:
  1125.       if(longitud<30) {
  1126.     nombre[longitud++]='v';
  1127.     nombre[longitud]=127;
  1128.     nombre[longitud+1]=0;
  1129.       }
  1130.       break;
  1131.     case SDLK_w:
  1132.       if(longitud<30) {
  1133.     nombre[longitud++]='w';
  1134.     nombre[longitud]=127;
  1135.     nombre[longitud+1]=0;
  1136.       }
  1137.       break;
  1138.     case SDLK_x:
  1139.       if(longitud<30) {
  1140.     nombre[longitud++]='x';
  1141.     nombre[longitud]=127;
  1142.     nombre[longitud+1]=0;
  1143.       }
  1144.       break;
  1145.     case SDLK_y:
  1146.       if(longitud<30) {
  1147.     nombre[longitud++]='y';
  1148.     nombre[longitud]=127;
  1149.     nombre[longitud+1]=0;
  1150.       }
  1151.       break;
  1152.     case SDLK_z:
  1153.       if(longitud<30) {
  1154.     nombre[longitud++]='z';
  1155.     nombre[longitud]=127;
  1156.     nombre[longitud+1]=0;
  1157.       }
  1158.       break;
  1159.     case SDLK_0:
  1160.       if(longitud<30) {
  1161.     nombre[longitud++]='0';
  1162.     nombre[longitud]=127;
  1163.     nombre[longitud+1]=0;
  1164.       }
  1165.       break;
  1166.     case SDLK_1:
  1167.       if(longitud<30) {
  1168.     nombre[longitud++]='1';
  1169.     nombre[longitud]=127;
  1170.     nombre[longitud+1]=0;
  1171.       }
  1172.       break;
  1173.     case SDLK_2:
  1174.       if(longitud<30) {
  1175.     nombre[longitud++]='2';
  1176.     nombre[longitud]=127;
  1177.     nombre[longitud+1]=0;
  1178.       }
  1179.       break;
  1180.     case SDLK_3:
  1181.       if(longitud<30) {
  1182.     nombre[longitud++]='3';
  1183.     nombre[longitud]=127;
  1184.     nombre[longitud+1]=0;
  1185.       }
  1186.       break;
  1187.     case SDLK_4:
  1188.       if(longitud<30) {
  1189.     nombre[longitud++]='4';
  1190.     nombre[longitud]=127;
  1191.     nombre[longitud+1]=0;
  1192.       }
  1193.       break;
  1194.     case SDLK_5:
  1195.       if(longitud<30) {
  1196.     nombre[longitud++]='5';
  1197.     nombre[longitud]=127;
  1198.     nombre[longitud+1]=0;
  1199.       }
  1200.       break;
  1201.     case SDLK_6:
  1202.       if(longitud<30) {
  1203.     nombre[longitud++]='6';
  1204.     nombre[longitud]=127;
  1205.     nombre[longitud+1]=0;
  1206.       }
  1207.       break;
  1208.     case SDLK_7:
  1209.       if(longitud<30) {
  1210.     nombre[longitud++]='7';
  1211.     nombre[longitud]=127;
  1212.     nombre[longitud+1]=0;
  1213.       }
  1214.       break;
  1215.         case SDLK_8:
  1216.             if(longitud<30) {
  1217.                 nombre[longitud++]='8';
  1218.                 nombre[longitud]=127;
  1219.                   nombre[longitud+1]=0;
  1220.             }
  1221.         break;
  1222.         case SDLK_9:
  1223.             if(longitud<30) {
  1224.                 nombre[longitud++]='9';
  1225.                 nombre[longitud]=127;
  1226.                   nombre[longitud+1]=0;
  1227.             }
  1228.         break;
  1229.         case SDLK_MINUS:
  1230.             if(longitud<30) {
  1231.                 nombre[longitud++]='-';
  1232.                   nombre[longitud]=127;
  1233.                   nombre[longitud+1]=0;
  1234.             }
  1235.         break;
  1236.         }
  1237.     } while(!retorno);
  1238.  
  1239.     clean_screen();
  1240.  
  1241.     nombre[longitud]=0; // erase cursor
  1242.  
  1243.     if(retorno==2) // abort
  1244.         return;
  1245.  
  1246.     longitud=strlen(path_mdrs);
  1247.     if((path_mdrs[longitud-1]!='/')&&(longitud>1))
  1248.         sprintf(nombre2,"%s/%s.mdr",path_mdrs,nombre); // name
  1249.     else
  1250.         sprintf(nombre2,"%s%s.mdr",path_mdrs,nombre);
  1251.         
  1252.     ordenador.mdr_file=fopen(nombre2,"r"); // test if it exists
  1253.     if(ordenador.mdr_file==NULL)
  1254.         retorno=0;
  1255.     else
  1256.         retorno=-1;
  1257.     
  1258.     if(!retorno) {
  1259.         ordenador.mdr_file=fopen(nombre2,"wb"); // create for write
  1260.         if(ordenador.mdr_file==NULL)
  1261.             retorno=-2;
  1262.         else {
  1263.             for(bucle=0;bucle<137921;bucle++)
  1264.                 ordenador.mdr_cartridge[bucle]=0xFF; // erase cartridge
  1265.             ordenador.mdr_cartridge[137922]=0;
  1266.             fwrite(ordenador.mdr_cartridge,137923,1,ordenador.mdr_file); // save cartridge
  1267.             fclose(ordenador.mdr_file);
  1268.             ordenador.mdr_file=NULL;
  1269.             ordenador.mdr_modified=0;
  1270.             retorno=0;
  1271.         }
  1272.     }    
  1273.     strcpy(ordenador.mdr_current_mdr,nombre2);    
  1274.     switch(retorno) {
  1275.     case 0:
  1276.     break;
  1277.     case -1:
  1278.         printstring(videomem,"File already exists",-1,80,26,16,ancho);
  1279.         ordenador.mdr_current_mdr[0]=0;
  1280.         wait_key();
  1281.     break;
  1282.     case -2:
  1283.         printstring(videomem,"Can't create file",-1,80,26,16,ancho);
  1284.         ordenador.mdr_current_mdr[0]=0;
  1285.         wait_key();
  1286.     break;
  1287.     }
  1288.     clean_screen();
  1289. }
  1290.  
  1291.  
  1292. // shows a menu to allow user to save a snapshot file
  1293.  
  1294. void save_z80file() {
  1295.  
  1296.   unsigned char *videomem;
  1297.   int ancho,retorno,longitud;
  1298.   unsigned char nombre[35],nombre2[37];
  1299.  
  1300.   videomem=screen->pixels;
  1301.   ancho=screen->w;
  1302.  
  1303.   clean_screen();
  1304.  
  1305.   printstring(videomem,"Choose a name for the snapshot",-1,32,30,16,ancho);
  1306.   printstring(videomem,"(up to 30 characters)",-1,52,30,16,ancho);
  1307.  
  1308.   printstring(videomem,"Snapshot will be saved in:",-1,132,28,16,ancho);
  1309.   printstring(videomem,path_snaps,0,152,28,16,ancho);
  1310.  
  1311.   nombre[0]=127;
  1312.   nombre[1]=0;
  1313.   longitud=0;
  1314.   retorno=0;
  1315.  
  1316.   do {
  1317.     sprintf(nombre2," %s ",nombre);
  1318.     printstring(videomem,nombre2,-1,84,31,16,ancho);
  1319.     switch(wait_key()) {
  1320.     case SDLK_BACKSPACE:
  1321.       if(longitud>0) {
  1322.     nombre[longitud]=0;
  1323.     longitud--;
  1324.     nombre[longitud]=127;
  1325.       }
  1326.       break;
  1327.     case SDLK_ESCAPE:
  1328.       retorno=2;
  1329.       break;
  1330.     case SDLK_RETURN:
  1331.       retorno=1;
  1332.       break;
  1333.     case SDLK_a:
  1334.       if(longitud<30) {
  1335.     nombre[longitud++]='a';
  1336.     nombre[longitud]=127;
  1337.     nombre[longitud+1]=0;
  1338.       }
  1339.       break;
  1340.     case SDLK_b:
  1341.       if(longitud<30) {
  1342.     nombre[longitud++]='b';
  1343.     nombre[longitud]=127;
  1344.     nombre[longitud+1]=0;
  1345.       }
  1346.       break;
  1347.     case SDLK_c:
  1348.       if(longitud<30) {
  1349.     nombre[longitud++]='c';
  1350.     nombre[longitud]=127;
  1351.     nombre[longitud+1]=0;
  1352.       }
  1353.       break;
  1354.     case SDLK_d:
  1355.       if(longitud<30) {
  1356.     nombre[longitud++]='d';
  1357.     nombre[longitud]=127;
  1358.     nombre[longitud+1]=0;
  1359.       }
  1360.       break;
  1361.     case SDLK_e:
  1362.       if(longitud<30) {
  1363.     nombre[longitud++]='e';
  1364.     nombre[longitud]=127;
  1365.     nombre[longitud+1]=0;
  1366.       }
  1367.       break;
  1368.     case SDLK_f:
  1369.       if(longitud<30) {
  1370.     nombre[longitud++]='f';
  1371.     nombre[longitud]=127;
  1372.     nombre[longitud+1]=0;
  1373.       }
  1374.       break;
  1375.     case SDLK_g:
  1376.       if(longitud<30) {
  1377.     nombre[longitud++]='g';
  1378.     nombre[longitud]=127;
  1379.     nombre[longitud+1]=0;
  1380.       }
  1381.       break;
  1382.     case SDLK_h:
  1383.       if(longitud<30) {
  1384.     nombre[longitud++]='h';
  1385.     nombre[longitud]=127;
  1386.     nombre[longitud+1]=0;
  1387.       }
  1388.       break;
  1389.     case SDLK_i:
  1390.       if(longitud<30) {
  1391.     nombre[longitud++]='i';
  1392.     nombre[longitud]=127;
  1393.     nombre[longitud+1]=0;
  1394.       }
  1395.       break;
  1396.     case SDLK_j:
  1397.       if(longitud<30) {
  1398.     nombre[longitud++]='j';
  1399.     nombre[longitud]=127;
  1400.     nombre[longitud+1]=0;
  1401.       }
  1402.       break;
  1403.     case SDLK_k:
  1404.       if(longitud<30) {
  1405.     nombre[longitud++]='k';
  1406.     nombre[longitud]=127;
  1407.     nombre[longitud+1]=0;
  1408.       }
  1409.       break;
  1410.     case SDLK_l:
  1411.       if(longitud<30) {
  1412.     nombre[longitud++]='l';
  1413.     nombre[longitud]=127;
  1414.     nombre[longitud+1]=0;
  1415.       }
  1416.       break;
  1417.     case SDLK_m:
  1418.       if(longitud<30) {
  1419.     nombre[longitud++]='m';
  1420.     nombre[longitud]=127;
  1421.     nombre[longitud+1]=0;
  1422.       }
  1423.       break;
  1424.     case SDLK_n:
  1425.       if(longitud<30) {
  1426.     nombre[longitud++]='n';
  1427.     nombre[longitud]=127;
  1428.     nombre[longitud+1]=0;
  1429.       }
  1430.       break;
  1431.     case SDLK_o:
  1432.       if(longitud<30) {
  1433.     nombre[longitud++]='o';
  1434.     nombre[longitud]=127;
  1435.     nombre[longitud+1]=0;
  1436.       }
  1437.       break;
  1438.     case SDLK_p:
  1439.       if(longitud<30) {
  1440.     nombre[longitud++]='p';
  1441.     nombre[longitud]=127;
  1442.     nombre[longitud+1]=0;
  1443.       }
  1444.       break;
  1445.     case SDLK_q:
  1446.       if(longitud<30) {
  1447.     nombre[longitud++]='q';
  1448.     nombre[longitud]=127;
  1449.     nombre[longitud+1]=0;
  1450.       }
  1451.       break;
  1452.     case SDLK_r:
  1453.       if(longitud<30) {
  1454.     nombre[longitud++]='r';
  1455.     nombre[longitud]=127;
  1456.     nombre[longitud+1]=0;
  1457.       }
  1458.       break;
  1459.     case SDLK_s:
  1460.       if(longitud<30) {
  1461.     nombre[longitud++]='s';
  1462.     nombre[longitud]=127;
  1463.     nombre[longitud+1]=0;
  1464.       }
  1465.       break;
  1466.     case SDLK_t:
  1467.       if(longitud<30) {
  1468.     nombre[longitud++]='t';
  1469.     nombre[longitud]=127;
  1470.     nombre[longitud+1]=0;
  1471.       }
  1472.       break;
  1473.     case SDLK_u:
  1474.       if(longitud<30) {
  1475.     nombre[longitud++]='u';
  1476.     nombre[longitud]=127;
  1477.     nombre[longitud+1]=0;
  1478.       }
  1479.       break;
  1480.     case SDLK_v:
  1481.       if(longitud<30) {
  1482.     nombre[longitud++]='v';
  1483.     nombre[longitud]=127;
  1484.     nombre[longitud+1]=0;
  1485.       }
  1486.       break;
  1487.     case SDLK_w:
  1488.       if(longitud<30) {
  1489.     nombre[longitud++]='w';
  1490.     nombre[longitud]=127;
  1491.     nombre[longitud+1]=0;
  1492.       }
  1493.       break;
  1494.     case SDLK_x:
  1495.       if(longitud<30) {
  1496.     nombre[longitud++]='x';
  1497.     nombre[longitud]=127;
  1498.     nombre[longitud+1]=0;
  1499.       }
  1500.       break;
  1501.     case SDLK_y:
  1502.       if(longitud<30) {
  1503.     nombre[longitud++]='y';
  1504.     nombre[longitud]=127;
  1505.     nombre[longitud+1]=0;
  1506.       }
  1507.       break;
  1508.     case SDLK_z:
  1509.       if(longitud<30) {
  1510.     nombre[longitud++]='z';
  1511.     nombre[longitud]=127;
  1512.     nombre[longitud+1]=0;
  1513.       }
  1514.       break;
  1515.     case SDLK_0:
  1516.       if(longitud<30) {
  1517.     nombre[longitud++]='0';
  1518.     nombre[longitud]=127;
  1519.     nombre[longitud+1]=0;
  1520.       }
  1521.       break;
  1522.     case SDLK_1:
  1523.       if(longitud<30) {
  1524.     nombre[longitud++]='1';
  1525.     nombre[longitud]=127;
  1526.     nombre[longitud+1]=0;
  1527.       }
  1528.       break;
  1529.     case SDLK_2:
  1530.       if(longitud<30) {
  1531.     nombre[longitud++]='2';
  1532.     nombre[longitud]=127;
  1533.     nombre[longitud+1]=0;
  1534.       }
  1535.       break;
  1536.     case SDLK_3:
  1537.       if(longitud<30) {
  1538.     nombre[longitud++]='3';
  1539.     nombre[longitud]=127;
  1540.     nombre[longitud+1]=0;
  1541.       }
  1542.       break;
  1543.     case SDLK_4:
  1544.       if(longitud<30) {
  1545.     nombre[longitud++]='4';
  1546.     nombre[longitud]=127;
  1547.     nombre[longitud+1]=0;
  1548.       }
  1549.       break;
  1550.     case SDLK_5:
  1551.       if(longitud<30) {
  1552.     nombre[longitud++]='5';
  1553.     nombre[longitud]=127;
  1554.     nombre[longitud+1]=0;
  1555.       }
  1556.       break;
  1557.     case SDLK_6:
  1558.       if(longitud<30) {
  1559.     nombre[longitud++]='6';
  1560.     nombre[longitud]=127;
  1561.     nombre[longitud+1]=0;
  1562.       }
  1563.       break;
  1564.     case SDLK_7:
  1565.       if(longitud<30) {
  1566.     nombre[longitud++]='7';
  1567.     nombre[longitud]=127;
  1568.     nombre[longitud+1]=0;
  1569.       }
  1570.       break;
  1571.     case SDLK_8:
  1572.       if(longitud<30) {
  1573.     nombre[longitud++]='8';
  1574.     nombre[longitud]=127;
  1575.     nombre[longitud+1]=0;
  1576.       }
  1577.       break;
  1578.     case SDLK_9:
  1579.       if(longitud<30) {
  1580.     nombre[longitud++]='9';
  1581.     nombre[longitud]=127;
  1582.     nombre[longitud+1]=0;
  1583.       }
  1584.       break;
  1585.     case SDLK_MINUS:
  1586.       if(longitud<30) {
  1587.     nombre[longitud++]='-';
  1588.     nombre[longitud]=127;
  1589.     nombre[longitud+1]=0;
  1590.       }
  1591.       break;
  1592.     }
  1593.   } while(!retorno);
  1594.  
  1595.   clean_screen();
  1596.  
  1597.   nombre[longitud]=0; // erase cursor
  1598.  
  1599.   if(retorno==2) // abort
  1600.     return;
  1601.  
  1602.   longitud=strlen(path_snaps);
  1603.   if((path_snaps[longitud-1]!='/')&&(longitud>1))
  1604.     sprintf(nombre2,"%s/%s.z80",path_snaps,nombre); // name
  1605.   else
  1606.     sprintf(nombre2,"%s%s.z80",path_snaps,nombre);
  1607.   retorno=save_z80(nombre2);
  1608.   switch(retorno) {
  1609.   case 0:    
  1610.     break;
  1611.   case -1:
  1612.     printstring(videomem,"File already exists",-1,80,26,16,ancho);
  1613.     wait_key();
  1614.     break;
  1615.   case -2:
  1616.     printstring(videomem,"Can't create file",-1,80,26,16,ancho);
  1617.     wait_key();
  1618.     break;
  1619.   }
  1620.   clean_screen();
  1621. }
  1622.  
  1623. // shows a menu to allow user to load a snapshot file
  1624.  
  1625. void load_z80file() {
  1626.  
  1627.  
  1628.   unsigned char *videomem,*filename;
  1629.   int ancho,retorno;
  1630.  
  1631.   videomem=screen->pixels;
  1632.   ancho=screen->w;
  1633.  
  1634.   clean_screen();
  1635.  
  1636.   printstring(videomem,"Choose the snapshot file to load",-1,32,29,16,ancho);
  1637.  
  1638.   filename=select_file(path_snaps,0);
  1639.  
  1640.   if(filename==NULL) { // Aborted
  1641.     clean_screen();
  1642.     return;
  1643.   }
  1644.  
  1645.   retorno=load_z80(filename);
  1646.   free(filename);
  1647.   clean_screen();
  1648.  
  1649.   switch(retorno) {
  1650.   case 0: // all right
  1651.     break;
  1652.   case -1:
  1653.     printstring(videomem,"Error: Can't load that file",-1,232,26,16,ancho);
  1654.     printstring(videomem,"Press any key",-1,248,26,16,ancho);
  1655.     wait_key();
  1656.     break;
  1657.   case -2:
  1658.   case -3:
  1659.     printstring(videomem,"Error: unsuported snap file",-1,232,26,16,ancho);
  1660.     printstring(videomem,"Press any key",-1,248,26,16,ancho);
  1661.     wait_key();
  1662.     break;
  1663.   }
  1664.   clean_screen();
  1665. }
  1666.  
  1667.  
  1668.  
  1669.  
  1670. /* fills a FICHERO chained list with all the files and directories contained in PATH.
  1671.    If KIND is 0, it returns only Snapshots, if is 1, it returns only TAPE files, and 
  1672.     if is 2, it returns only MDR files */
  1673.  
  1674. struct fichero *read_directory(char *cpath,char kind) {
  1675.  
  1676.     struct fichero *listhead,*listend;
  1677.     struct dirent *entry;
  1678.     DIR *directory;
  1679.     struct stat estado;
  1680.     unsigned char path[2049],fichero[2049],extension[5],found;
  1681.     int bucle,length;  
  1682.  
  1683.     if((kind!=0)&&(kind!=1)&&(kind!=2))
  1684.         printf("Error!!!!\n");
  1685.     
  1686.     strcpy(path,cpath);
  1687.     if('/'!=path[strlen(path)-1])
  1688.         strcat(path,"/"); // add the final / to the path    
  1689.  
  1690.     listhead=malloc(sizeof(struct fichero));
  1691.     strcpy(listhead->nombre,"..");
  1692.     listhead->tipo=2;
  1693.     listhead->next=NULL;
  1694.     listend=listhead;
  1695.  
  1696.     directory=opendir(path);
  1697.     if(directory==NULL)
  1698.         return(listhead); // can't access the directory
  1699.   
  1700.     do {
  1701.         entry=readdir(directory);
  1702.         if((NULL!=entry)&&(strcmp(entry->d_name,"."))&&(strcmp(entry->d_name,".."))) {
  1703.             strcpy(fichero,path);
  1704.             strcat(fichero,entry->d_name);
  1705.             stat(fichero,&estado);            
  1706.             found=0; // by default is not a valid file...
  1707.             length=strlen(entry->d_name);            
  1708.             if(length>3) {
  1709.                 extension[4]=0;
  1710.                 for(bucle=0;bucle<4;bucle++)
  1711.                     extension[bucle]=entry->d_name[length-4+bucle]; // copy the 4 last chars of the file (the extension)
  1712.                 switch(kind) {
  1713.                 case 0:
  1714.                     if(!strcasecmp(extension,".z80"))
  1715.                         found=1; // is a .z80 file
  1716.                 break;
  1717.                 case 1:
  1718.                     if((!strcasecmp(extension,".tap"))||(!strcasecmp(extension,".tzx")))
  1719.                         found=1; // is a .tap file
  1720.                 break;
  1721.                 case 2:
  1722.                     if(!strcasecmp(extension,".mdr"))
  1723.                         found=1; // is a .mdr file
  1724.                 break;
  1725.                 default:
  1726.                 break;
  1727.                 }
  1728.             } else
  1729.                 found=0;            
  1730.             if(((found)||(S_ISDIR(estado.st_mode)))&&('.'!=entry->d_name[0])) { // is a directory. We must add it                
  1731.                 listend->next=malloc(sizeof(struct fichero));      
  1732.                 listend=listend->next;
  1733.                 listend->next=NULL;
  1734.                 strcpy(listend->nombrepath,fichero);
  1735.                 strcpy(listend->nombre,entry->d_name);
  1736.                 if(S_ISDIR(estado.st_mode))
  1737.                     listend->tipo=1; // a directory
  1738.                 else
  1739.                     listend->tipo=0; // a file
  1740.             }
  1741.         }
  1742.     } while(entry!=NULL);
  1743.     closedir(directory);
  1744.     return(listhead);
  1745. }
  1746.  
  1747. // deletes a filelist tree, freeing the memory used by it
  1748.  
  1749. void delete_filelist(struct fichero *filelist) {
  1750.  
  1751.   struct fichero *fl1,*fl2;
  1752.  
  1753.   fl1=fl2=filelist;
  1754.  
  1755.   while(fl1!=NULL) {
  1756.     fl2=fl1->next;
  1757.     free(fl1);
  1758.     fl1=fl2;
  1759.   }
  1760. }
  1761.  
  1762.  
  1763. /* allows user to choose a file from PATH. If KIND=0, only snapshots. If KIND=1, only
  1764.    TAPE files */
  1765.  
  1766. char *select_file(char *path,char kind) {
  1767.  
  1768.   struct fichero *filelist,*fl2;
  1769.   unsigned char *pantalla,*pantalla2,fin,read,*salida;
  1770.   int bucle,ancho,numitems,selected,from,longitud;
  1771.  
  1772.   salida=(unsigned char *)malloc(2049);
  1773.   salida[0]=0;
  1774.  
  1775.   ancho=screen->w;
  1776.  
  1777.   // paints the rectangle
  1778.  
  1779.   pantalla=(screen->pixels)+(ancho*70)+10;
  1780.   pantalla2=(screen->pixels)+(ancho*460)+10;
  1781.   for(bucle=10;bucle<630;bucle++) {
  1782.     *(pantalla++)=28;
  1783.     *(pantalla2++)=28;
  1784.   }
  1785.   pantalla=(screen->pixels)+(ancho*70)+10;
  1786.   pantalla2=(screen->pixels)+(ancho*70)+630;
  1787.   for(bucle=70;bucle<460;bucle++) {
  1788.     *pantalla=28;
  1789.     *pantalla2=28;
  1790.     pantalla+=ancho;
  1791.     pantalla2+=ancho;
  1792.   }
  1793.  
  1794.   fin=1;
  1795.   read=1;
  1796.   selected=0;
  1797.   from=0;
  1798.   numitems=0;
  1799.  
  1800.   filelist=NULL;
  1801.  
  1802.   do {
  1803.  
  1804.     if(read) {
  1805.       filelist=read_directory(path,kind);
  1806.       read=0;
  1807.  
  1808.       fl2=filelist;
  1809.       numitems=0;
  1810.       while(fl2!=NULL) { // counts the number of items
  1811.     fl2=fl2->next;
  1812.     numitems++;
  1813.       }
  1814.       selected=0;
  1815.       from=0;
  1816.     }
  1817.  
  1818.     print_files(filelist,from,selected);
  1819.  
  1820.     switch(wait_key()) {
  1821.     case SDLK_ESCAPE: // to exit the help
  1822.       fin=0;
  1823.       break;
  1824.  
  1825.     case SDLK_UP:
  1826.       if(selected>0) {
  1827.     selected--;
  1828.     if(selected<from)
  1829.       from--;
  1830.       }
  1831.       break;
  1832.     case SDLK_DOWN:
  1833.       if(selected<(numitems-1)) {
  1834.     selected++;
  1835.     if(selected>(from+23)) // 23 is the total of items that can be displayed
  1836.       from++;
  1837.       }
  1838.       break;
  1839.  
  1840.     case SDLK_PAGEUP:
  1841.       for(bucle=0;bucle<15;bucle++)
  1842.     if(selected>0) {
  1843.       selected--;
  1844.       if(selected<from)
  1845.         from--;
  1846.     }
  1847.       break;
  1848.  
  1849.     case SDLK_PAGEDOWN:
  1850.       for(bucle=0;bucle<15;bucle++)
  1851.     if(selected<(numitems-1)) {
  1852.       selected++;
  1853.       if(selected>(from+23)) // 23 is the total of items that can be displayed
  1854.         from++;
  1855.     }
  1856.       break;
  1857.  
  1858.     case SDLK_RETURN:
  1859.       fl2=filelist;
  1860.       if(selected!=0)
  1861.     for(bucle=0;bucle<selected;bucle++)
  1862.       fl2=fl2->next;
  1863.       switch(fl2->tipo) {
  1864.       case 0: // select file
  1865.     strcpy(salida,fl2->nombrepath);
  1866.     delete_filelist(filelist);
  1867.     return(salida); // ends returning the filename
  1868.       case 1: // change directory
  1869.     strcpy(path,fl2->nombrepath); // new path_taps is namepath
  1870.     delete_filelist(filelist); // frees the memory
  1871.     read=1; // and redisplay all the files
  1872.     break;
  1873.       case 2: // upper directory
  1874.     longitud=strlen(path);
  1875.     if(longitud<2) // there's no upper directory
  1876.       break;
  1877.     if('/'==path[longitud-1]) { // is the char ended in '/' ?
  1878.       path[longitud-1]=0; // eliminated
  1879.       longitud--;
  1880.     }
  1881.     while('/'!=path[longitud-1]) {
  1882.       longitud--;
  1883.       path[longitud]=0;
  1884.     }
  1885.     if(longitud>2) { // it's not the upper directory
  1886.       longitud--;
  1887.       path[longitud]=0; // delete the final '/'
  1888.     }
  1889.     read=1;
  1890.     break;
  1891.       default:
  1892.     break;
  1893.       }
  1894.  
  1895.     default:
  1896.       break;
  1897.     }
  1898.   } while(fin);
  1899.  
  1900.   delete_filelist(filelist);
  1901.   return(NULL);
  1902.  
  1903. }
  1904.  
  1905. void clean_screen() {
  1906.  
  1907.   int bucle;
  1908.   unsigned char *buffer;
  1909.  
  1910.   buffer=screen->pixels;
  1911.  
  1912.   for(bucle=0;bucle<((screen->h)*(screen->w));bucle++)
  1913.     *(buffer++)=16;
  1914.  
  1915. }
  1916.  
  1917. // waits for a keystroke and returns its value
  1918.  
  1919. unsigned int wait_key() {
  1920.  
  1921.   char fin;
  1922.   unsigned int temporal_io=0;
  1923.   SDL_Event evento;
  1924.  
  1925.   fin=1;
  1926.  
  1927.   do {
  1928.     SDL_Flip(ordenador.screen);
  1929.     if(!SDL_WaitEvent(&evento))
  1930.       continue;
  1931.     
  1932.     if(evento.type!=SDL_KEYUP)
  1933.       continue;
  1934.  
  1935.     fin=0;
  1936.     
  1937.     temporal_io=(unsigned int)evento.key.keysym.sym;
  1938.   } while(fin);
  1939.  
  1940.   return (temporal_io);
  1941. }
  1942.  
  1943. // shows the files from the number FROM, and marks the file number MARK
  1944.  
  1945. void print_files(struct fichero *filelist,int from,int mark) {
  1946.  
  1947.   struct fichero *fl2;
  1948.   int bucle,numitems,ancho,pos;
  1949.   char ink1,ink2;
  1950.   unsigned char spaces[39]="                                      ";
  1951.   unsigned char namefile[2089];
  1952.   unsigned char *videomem;
  1953.  
  1954.   videomem=screen->pixels;
  1955.   ancho=screen->w;
  1956.  
  1957.   fl2=filelist;
  1958.   numitems=0;
  1959.  
  1960.   while(fl2!=NULL) { // counts the number of items
  1961.     fl2=fl2->next;
  1962.     numitems++;
  1963.   }
  1964.  
  1965.   ink1=ink2=0;
  1966.  
  1967.   fl2=filelist;
  1968.   pos=72;
  1969.   for(bucle=0;bucle<numitems;bucle++) {
  1970.     if(bucle>=from) {
  1971.       strcpy(namefile,fl2->nombre);
  1972.       strcat(namefile,spaces);
  1973.       namefile[36]=0; // we print up to 36 chars
  1974.       switch(fl2->tipo) {
  1975.       case 0: // file
  1976.     ink1=31;
  1977.     ink2=16;
  1978.     break;
  1979.       case 1: // directory
  1980.     ink1=28;
  1981.     ink2=20;
  1982.     break;
  1983.       case 2: // parent directory
  1984.     ink1=26;
  1985.     ink2=18;
  1986.     break;
  1987.       }
  1988.       if(bucle==mark)
  1989.     printstring(videomem,namefile,-1,pos,ink2,31,ancho);
  1990.       else
  1991.     printstring(videomem,namefile,-1,pos,ink1,16,ancho);
  1992.       pos+=16;
  1993.     }
  1994.     if((pos+16)>460)
  1995.       break; // reached bottom part of the rectangle
  1996.     fl2=fl2->next;
  1997.   }
  1998.   while((pos+16<460)) {
  1999.     printstring(videomem,spaces,-1,pos,16,16,ancho);
  2000.     pos+=16;
  2001.   }
  2002. }
  2003.